/**
 * 
 */
package testing;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import sagroup.dracots.DracoTS;

import lights.adapters.Field;
import lights.adapters.Tuple;
import lights.interfaces.ITuple;
import lime2.AgentCreationException;
import lime2.BootException;
import lime2.LimeServer;
import lime2.LimeTemplate;
import lime2.LimeTupleSpace;
import lime2.Location;
import lime2.PolicyException;

/**
 * Provide a runtime console to control Lime 2 system
 * @author Xing Jiankuan
 *
 */
public class ControlConsole implements Runnable {

	private BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); 
	
	private LimeServer server = LimeServer.getServer();
	public void run() {
		String cmd;
		String[] tokens = null;
		String[] paras = null;
		Thread.currentThread().setName("ControlConsole");
		LimeTupleSpace ts = LimeTupleSpace.get("testing");
		if(ts == null) {
			System.out.println("Load dts fail");
			System.exit(1);
		}
		// the testing tuple space
		while(true)
		{
			System.out.print(server.getServerID().toString() + ">");
			try {
				cmd = input.readLine();
				tokens = cmd.split("(" + (char)32 + "|" + (char)9 + ")+");
				if (tokens[0].compareToIgnoreCase("load") == 0) {
					paras = new String[tokens.length - 2];
					System.arraycopy(tokens, 2, paras, 0, paras.length);
					server.loadAgent(tokens[1], paras);
				} else if(tokens[0].compareToIgnoreCase("add") == 0) {
					if(tokens.length != 2 && tokens.length != 4) {
						throw new Exception("Illegal command format");
					}
					performAdd(tokens);
				} else if (tokens[0].compareToIgnoreCase("boot") == 0) {
					server.boot();
				} else if (tokens[0].compareToIgnoreCase("shutdown") == 0) {
					server.shutdown(); // the whole system will be shut down, any agent will be unloaded.
				} else if (tokens[0].compareToIgnoreCase("addr") == 0) {
					System.out.println("Unicast:"
							+ server.getUnicastAddress().getHostAddress() + "("
							+ server.getUnicastAddress().getHostName() + "):"
							+ server.getUnicastPort() + " Multicast:"
							+ server.getMulticastAddress() + ":"
							+ server.getMulticastPort());
				} else if (tokens[0].compareToIgnoreCase("help") == 0) {
					System.out
							.println("Usage:\n"
									+ "boot \"boot the lime server\"\n"
									+ "shutdown \"shut down the whole system\"\n"
									+ "addr \"show local address information\"\n"
									+ "load agent-qualified-name [parameter [parameter ...]] \"load an agent\""
									+ "add [ip] [port] count \"write tuples to somewhere for test\"\n");
				}
			} catch (IOException e) {
				e.printStackTrace();
			} catch (AgentCreationException e) {
				System.out.println("Unable to load agent:" + tokens[1] + " with parameters:" + paras.toString());
			} catch (BootException e) {
				System.out.println(e.getMessage());
			} catch (Exception e) {
				System.out.println(e.getMessage());
			}
		}
		
	}
	//out specified number of tuples to a node
	private void performAdd(String[] tokens) {
		LimeTupleSpace ts = LimeTupleSpace.get("testing");
		if(tokens.length == 2) {
			//local case
			int count = Integer.parseInt(tokens[1]);
			for(int i = 0; i < count; i++) {
				ITuple t = new Tuple().add(new Field().setValue("localString" + i));
				ts.out(Location.HERE, t);
			}
		} else {
			//remote case
			Location whereTo = Location.build(tokens[1], Integer.parseInt(tokens[2]));
			int count = Integer.parseInt(tokens[3]);
			for(int i = 0; i < count; i++) {
				ITuple t = new Tuple().add(new Field().setValue("remoteString" + i));
				ts.out(whereTo, t);
			}
		}
		
	}

}
